package com.nmmhu.utils;
import com.nmmhu.annotation.UserAnnotation;
import com.nmmhu.bean.UserInfo;

import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author nmm
 * @date 2024-03-2024/3/11
 * @deriction njm......
 */
    public class CrudUtil {

        private  static Connection conn = DbUtil.getConnection();
        private  static PreparedStatement psmt;
        private  static ResultSet rs;


        /**
         * 增删改的通用方法
         * @param sql 增删改sql语句
         * @param params 参数值
         * @return 受影响行数
         * @throws SQLException 异常
         */
        public static int executeUpdate(String sql,Object...params) throws SQLException {
            psmt = conn.prepareStatement(sql);
            if (params != null ) {
                for (int i = 0; i < params.length; i++) {
                    psmt.setObject(i + 1, params[i]); // 设置参数值
                }
            }
            int rows = psmt.executeUpdate(); // 执行sql
            // 关闭对象
            DbUtil.close(rs,psmt,conn);//关闭资源
            return rows;
        }


        /**
         * 查询的通用方法
         * @param sql 查询的sql语句
         * @param params 参数
         * @return 返回结果集
         * @throws SQLException
         */
        public static ResultSet executeQuery(String sql, Object...params) throws SQLException {
            psmt = conn.prepareStatement(sql);
            if (params != null ) {
                for (int i = 0; i < params.length; i++) {
                    psmt.setObject(i + 1, params[i]); // 设置参数值
                }
            }
            rs = psmt.executeQuery(); // 执行查询
            return rs;
        }


        /***
         * @desc: 该方法主要通过数据集,类注解,以及元数据实现
          *@param sql:要执行的sql语句
         * @param clazz:具体的class实例
         * @param param:sql语句参数值
         * @return   返回查询后存放对象的list集合
         * @param <T> //泛型
         * @throws Exception
         */
         public static <T> List<T>  QueryByAnnotation(String sql, Class<T> clazz, Object...param)throws Exception {
            List<T> list=new ArrayList<>();//创建list 用于将字段(属性)名改完的对象保存起来,并返回出去
            ResultSet res = executeQuery(sql, param);//返回数据集
            ResultSetMetaData metaData = res.getMetaData();//通过数据集拿到元数据
            int columnCount = metaData.getColumnCount();//返回元数据的列数(也就是数据表的列数)

             while (res.next()){
             T myClazz= clazz.newInstance();//通过clazz实例创建对象

             for (int i = 1; i <columnCount; i++) {//这里从1开始遍历元数据的信息
                 System.out.println(res.getObject(i));//对象属性值
                 String columnName = metaData.getColumnName(i);//返回元数据列名
                 String columnTypeName = metaData.getColumnTypeName(i);// 返回元数据属性类型
                 Field[] declaredFields = clazz.getDeclaredFields();//拿到当前clazz实例的所有属性

                 for (Field field : declaredFields) {
                     if (field.isAnnotationPresent(UserAnnotation.class)){
                         UserAnnotation myUserAno = field.getAnnotation(UserAnnotation.class);//拿到打上的注解

                         if (myUserAno.equals(columnName)){//如果打上的注解和元数据的列名一样
                             field.setAccessible(true);
                             field.set(myClazz,res.getObject(i));
                         }
                     }
                 }
             }
             list.add(myClazz);
            }
             return list;
        }


        //！！！重点理解上面用注解和用对象赋值的区别(优缺点)
        //QueryByAnnotation 和 QueryByLikeNam 共同点:都是通过Result数据集给对象进行赋值操作
        //不同点:QueryByLikeNam 局限性大:只能对具体的对象进行查询后赋值操作
        //QueryByAnnotation 通过反射获取class实例,并通过实例创建对象   再通过Result拿到元数据,然后遍历class的所有属性值通过属性值拿到其注解
        //再与元数据的列名进行对比相等就给对象进行赋值操作

        /***
         *
         * @param sql:要执行的sql语句
         * @param likeName：sql语句模糊查询参数值
         * @return: list 返回模糊查询后存储对象的list集合
         * @throws SQLException
         */
        public static List<UserInfo> QueryByLikeName(String sql,String likeName) throws  SQLException{
            List<UserInfo> userInfoList=new ArrayList<>();
            ResultSet res = executeQuery(sql,"%"+likeName+"%");

            while (res.next()){
            UserInfo user=new UserInfo();
            user.setId(res.getInt(1));
            user.setName(res.getString(2));
            user.setAge(res.getInt(3));
            user.setPhone(res.getString(4));
            user.setStaPos(res.getString(5));
            user.setAddTime(res.getTimestamp(6).toLocalDateTime());
            user.setUpdateTime(res.getTimestamp(7).toLocalDateTime());
            userInfoList.add(user);
            }
           return  userInfoList;
        }


        public static void main(String[] args) {
    //        try {
    //            ResultSet resultSet = new CrudUtil().executeQuery("select * from user_info");
    //            ResultSetMetaData metaData = resultSet.getMetaData();//获取元数据
    //
    //            System.out.println("aaa");
    //            int columnCount = metaData.getColumnCount();//获取列的总数
    //
    //            System.out.println("cccc");
    //            for (int i = 1; i < columnCount+1; i++) {
    //                System.out.println( "字段名"+metaData.getColumnName(i)+"字段类型"+metaData.getColumnTypeName(i)+metaData.getColumnLabel(i));
    //            }
    //        } catch (SQLException e) {
    //            e.getMessage();
    //        }


        }


    }